﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

using System.Reflection;

using Javavaj.iHunter;
using Javavaj.iHunter.Core;
using Javavaj.iHunter.Database;
using Javavaj.iHunter.Searching;


namespace Javavaj.iHunter.Core
{
    public partial class ClientCore : Component
    {
        Dictionary<int, IChannel> channels;
        IChannel dummyChannel = new DummyChannel();
        System.Threading.Mutex dbMutex;

        public ClientCore()
        {
            InitializeComponent();
        }

        public ClientCore(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }

        public void Initialize()
        {

            OpenDatabase();

            LoadPlugins();

            InitChannels();
        }

        #region Private methods

        private void OpenDatabase()
        {

            try
            {
                dbMutex = new System.Threading.Mutex(true, Properties.Settings.Default.DbMutexName);

            }
            catch (ApplicationException e)
            {
                throw new DatabaseOpenException("", e);
            }

            string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "iHunter");

            dbPath = Path.Combine(dbPath, Properties.Settings.Default.DbFileName);
            if (!File.Exists(dbPath))
            {
                CreateDatabase(dbPath);
            }
            try
            {
                userDbDataSet.Clear();
                byte[] bytes = File.ReadAllBytes(dbPath);
                byte[] buffer = System.Security.Cryptography.ProtectedData.Unprotect(
                    bytes,
                    null,
                     System.Security.Cryptography.DataProtectionScope.CurrentUser
                     );
                MemoryStream stream = new MemoryStream(buffer);

                userDbDataSet.ReadXml(stream);

                stream.Close();

            }
            catch (Exception e)
            {
                throw new DatabaseOpenException("", e);
            }
            userDbDataSet.Attachments.AttachmentsRowDeleting += new UserDbDataSet.AttachmentsRowChangeEventHandler(Attachments_AttachmentsRowDeleting);
        }

        void Attachments_AttachmentsRowDeleting(object sender, UserDbDataSet.AttachmentsRowChangeEvent e)
        {
       
            try
            {
                File.Delete(e.Row.LocalPath);
            }
            catch
            {
            }
        }

 

        private void CreateDatabase(string dbPath)
        {
            foreach (var row in userDbDataSet.Attachments)
            {
                try
                {
                    File.Delete(row.LocalPath);
                }
                catch
                {
                }
            }
            userDbDataSet.Clear();

            SaveDatabase();
            OpenDatabase();
        }

        private void LoadPlugins()
        {
            //Load Plugins
            pluginManager.LoadPlugins();
        }

        private void InitChannels()
        {
            channels = new Dictionary<int, IChannel>();
            channels.Add(dummyChannel.ComputeHash(), dummyChannel);
            foreach (IChannelFactory factory in pluginManager.ListPlugins(PluginType.ChannelPlugin))
            {
                foreach (IChannel channel in factory.ListChannels())
                {
                    channel.EditReply += new EditReplyEventHandler(channel_EditReply);
                    channels[channel.ComputeHash()] = channel;
                }
            }
            OnChannelChanged();

        }

        void channel_EditReply(object sender, EditReplyEventArgs e)
        {
            OnEditReply(e.Channel,e.Source,e.ReplyItems,e.Tag);
        }

        private void OnEditReply(IChannel channel, IMessage source,KeyValuePair<string,EditItemType>[] items,string tag)
        {
            if (this.EditReply != null)
                this.EditReply.Invoke(this, new EditItemsEventArgs(channel, source, items, tag));
        }

        protected void OnChannelChanged()
        {
            if (ChannelChanged != null)
                ChannelChanged.Invoke(this, EventArgs.Empty);
        }

        private void SaveDatabase()
        {
            try
            {
                string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "iHunter");
                if (!Directory.Exists(dbPath))
                    Directory.CreateDirectory(dbPath);
                MemoryStream stream = new MemoryStream();
                userDbDataSet.WriteXml(stream);
                byte[] buffer = System.Security.Cryptography.ProtectedData.Protect(
                  stream.ToArray(),
                  null,
                   System.Security.Cryptography.DataProtectionScope.CurrentUser
                   );
                dbPath = Path.Combine(dbPath, Properties.Settings.Default.DbFileName);

                File.WriteAllBytes(dbPath, buffer);


            }
            catch
            {
                OnErrorOccured("Cannot save database.", true);
            }
        }

        public void SaveMessageAsXml(IMessage header, string path)
        {
            try
            {
                IMessage message = GetMessage(header);
                if (message == null)
                    return;

                Message msg = new Message(channels[message.ChannelHash])
                {
                    Attachments = message.Attachments,
                    Author = message.Author,
                    Category = message.Category,
                    Content = message.Content,
                    ContentType = message.ContentType,
                    Description = message.Description,
                    DueTime = message.DueTime,
                    Importance = message.Importance,
                    LastBuildTime = message.LastBuildTime,
                    Link = message.Link,
                    PubTime = message.PubTime,
                    Read = message.Read,
                    Repliable = message.Repliable,
                    Title = message.Title,
                    Uid = message.Uid,
                    Id = message.Id
                };


                XmlWriter wt = XmlWriter.Create(path);
                msg.WriteXml(wt);
                wt.Close();
                return;
            }
            catch
            {
                OnErrorOccured("Save item failed.", true);
                return;
            }
        }


        #endregion

        #region 数据库管理操作

        ///<summary>
        ///建立新的数据库
        ///</summary>
        public void CreateNewDatabase()
        {
            try
            {
                CreateDatabase(Properties.Settings.Default.DbFileName);
                OnChannelChanged();
            }
            catch
            {
                OnErrorOccured("Cannot create database.", true);
                return;
            }
            return;
        }
        public void CleanDatabase()
        {
            for (int i = 0; i < userDbDataSet.Messages.Count;i++ )
            {
                UserDbDataSet.MessagesRow row = userDbDataSet.Messages[i];
                if (!channels.ContainsKey(row.ChannelHash))
                    row.Delete();

            }
            for (int i = 0; i < userDbDataSet.PluginSettings.Count; i++)
            {
                UserDbDataSet.PluginSettingsRow row = userDbDataSet.PluginSettings[i];
                var result = from info in pluginManager.GetPluginInformations(true)
                             where info.Assembly == row.AssemblyName
                             select info;
                if (result.Count() == 0)
                    row.Delete();
            }
            userDbDataSet.AcceptChanges();
        }
        public void ClearMessages()
        {
            try
            {
                foreach (var row in userDbDataSet.Attachments)
                {
                    try
                    {
                        File.Delete(row.LocalPath);
                    }
                    catch
                    {
                    }
                }
                userDbDataSet.Attachments.Clear();
                userDbDataSet.Messages.Clear();
                userDbDataSet.ChannelSettings.Clear();
                userDbDataSet.AcceptChanges();
                CleanDatabase();
                OnChannelChanged();
            }
            catch
            {
                OnErrorOccured("Failed to clean database.", true);
                return;
            }
            return;
        }
        public void ClearPluginSettings()
        {
            try
            {

                userDbDataSet.PluginSettings.Clear();
                CleanDatabase();
                LoadPlugins();
                InitChannels();

                OnChannelChanged();
            }
            catch
            {
                OnErrorOccured("Failed to clean database.", true);
                return;
            }
            return;
        }

        public void ResetGlobalSettings()
        {
            try
            {

                userDbDataSet.GlobalSettings.Clear();

            }
            catch
            {
                OnErrorOccured("Failed to clean database.", true);
                return;
            }
            return;
        }


        ///<summary>
        ///导出数据库
        ///</summary>
        public void ExportDatabase(string pathName)
        {
            try
            {
                userDbDataSet.WriteXml(pathName, System.Data.XmlWriteMode.IgnoreSchema);
            }
            catch
            {
                OnErrorOccured("Export database failed.", true);

                return;
            }
            return;
        }

        ///<summary>
        ///导入数据库
        ///</summary>
        public void ImportDatabase(string pathName)
        {
            try
            {
                UserDbDataSet ds = new UserDbDataSet();
                ds.ReadXml(pathName, System.Data.XmlReadMode.IgnoreSchema);
                userDbDataSet.Merge(ds,true, System.Data.MissingSchemaAction.Ignore);
                

            }
            catch
            {
                return;
            }
            return;
        }

        #endregion

        public PluginInformation[] GetPlugins()
        {
            return (GetPlugins(PluginType.ChannelPlugin).Union(GetPlugins(PluginType.FilterPlugin).Union(GetPlugins(PluginType.ViewerPlugin)))).ToArray();


        }

        public PluginInformation[] GetPlugins(PluginType type)
        {
            return pluginManager.GetPluginInformations(true);
        }
        ///<summary>
        ///添加插件
        ///</summary>
        public void AddPlugin(string assemblyPathName)
        {
            try
            {
                string assemblySearchPath = Path.Combine(
                      Path.Combine(
                          Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                          "iHunter"
                          ),
                      "Plugins"
                      );
                string newPath = Path.Combine(assemblySearchPath, Path.GetFileName(assemblyPathName));
                File.Copy(assemblyPathName, newPath,true);


                pluginManager.LoadPluginFromAssembly(newPath, false);
                return;
            }
            catch
            {
                OnErrorOccured("Failed to install plugin.", true);

                return;
            }
            finally
            {
                LoadPlugins();
                InitChannels();
            }
        }

        ///<summary>
        ///删除插件
        ///</summary>
        public void DeletePlugin(PluginInformation plugin)
        {
            try
            {
                File.Delete(plugin.FullPath);
            }
            catch
            {
                OnErrorOccured("Failed to delete plugin.", true);

                return;
            }
            if (!configManager.PluginSettings.Remove(plugin.Assembly))
                return;
            LoadPlugins();
            InitChannels();
            return;
        }

        public void SetPluginInformation(PluginInformation info)
        {
            pluginManager.SetPluginInfo(info);
            LoadPlugins();
            InitChannels();
            return;
        }

        ///<summary>
        ///配置插件(和过滤器)
        ///</summary>
        public void ConfigPlugin(PluginInformation info)
        {
            IPlugin plugin = pluginManager.GetPlugin(info);
            if (plugin == null)
                return;
            plugin.Config();

        }


        ///<summary>
        ///获得频道列表
        ///</summary>
        public IChannel[] GetChannels()
        {
            var channels = this.channels.Values;
            var result = new List<IChannel>();
            foreach (IChannel channel in channels.ToArray())
            {
                if (channel.ComputeHash() == dummyChannel.ComputeHash())
                {
                    //If it is empty, do not display it.
                    var categories = userDbDataSet.Messages.GetCategories(dummyChannel.ComputeHash());
                    if (categories.Count() == 0)
                        continue;
                }
                result.Add(channel);
            }
            return result.ToArray();

        }

        public string[] GetChannelCategories(IChannel channel)
        {
            return userDbDataSet.Messages.GetCategories(channel.ComputeHash());
        }
        public int GetUnreadNumber(IChannel channel, string category, bool spam)
        {
            var result = from row in userDbDataSet.Messages
                         where (row.Status & 1) == 0 &&
                         (channel.ComputeHash() == row.ChannelHash) &&
                         (category == null || category == row.Category) &&
                         ((spam && (row.Status & 2) != 0) || (!spam && (row.Status) ==0)) &&
                         (!row.Read)
                         select row;
            return result.Count();
        }

        ///<summary>
        ///获取(Channel,category,new/all)指定的消息头列表
        ///</summary>
        public IMessage[] GetMessageHeaders(IChannel channel, string category)
        {
            userDbDataSet.Messages.Select();
            //FIXME.
            var result = from row in userDbDataSet.Messages
                         where (row.Status & 1) == 0 &&
                         (row.ChannelHash == channel.ComputeHash() && (category == null || row.Category == category))
                         select row.CreateMessageHeader();
            return result.ToArray();
        }

        ///<summary>
        ///由消息头获取完整的消息对象
        ///</summary>
        public IMessage GetMessage(IMessage header)
        {
            UserDbDataSet.MessagesRow row = userDbDataSet.Messages.FindById(header.Id);
            if (row == null)
                return null;
            if ((row.Status & 1) != 0)
                return null;

            return row.CreateMessage();

        }

        /// <summary>
        /// 新建一条消息
        /// </summary>
        /// <param name="Channel">消息所属的频道</param>
        /// <returns>建立的消息头信息</returns>
        public IMessage NewMessage(IChannel channel)
        {
            int id = userDbDataSet.Messages.NewMessage();
            return new MessageHeader()
            {
                ChannelHash = channel.ComputeHash(),
                Id = id
            };
        }

        /// <summary>
        /// 删除一条消息
        /// </summary>
        /// <param name="message">要删除的消息或消息头</param>
        /// <returns>若删除成功，返回“真”(True)；若数据库中不存在指定的消息或删除失败，返回“假”(False)</returns>
        public void DeleteMessage(IMessage header)
        {
            var row = userDbDataSet.Messages.FindById(header.Id);
            if (row == null)
                return;
            userDbDataSet.Messages.DeleteMessage(header.Id);
        }
        

        /// <summary>
        /// 更新数据库中的消息
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public void UpdateMessage(IMessage message)
        {
            UpdateMessage(message, false);
        }

        public void UpdateMessage(IMessage message, bool recreateAttachments)
        {
         
          

            UserDbDataSet.MessagesRow row = userDbDataSet.Messages.FindById(message.Id);
            if (row == null)
                return;

            userDbDataSet.Messages.UpdateMessage(message);

            if (recreateAttachments)
            {
                foreach (UserDbDataSet.AttachmentsRow existingAttcRow in row.GetAttachmentsRows())
                {
                    existingAttcRow.Delete();
                }
                userDbDataSet.Attachments.AcceptChanges();

                foreach (IFileObject attachment in message.Attachments)
                {
                    StoreAttachment(message, attachment);
                }
                userDbDataSet.AcceptChanges();
            }

            return;


        }

        private IFileObject NewAttachment(IMessage message)
        {
            UserDbDataSet.AttachmentsRow row = userDbDataSet.Attachments.NewAttachmentsRow();
            row.MessageId = message.Id;
            row.Filename = "";
            row.Size = 0;
            row.Uri = "";
            row.Description = "";
            userDbDataSet.Attachments.AddAttachmentsRow(row);
            return new Attachment("", "", 0, "", "")
            {
                Id = row.Id
            };
        }

        private bool StoreAttachment(IMessage message, IFileObject attachment)
        {

            
            try
            {
                UserDbDataSet.AttachmentsRow row = null;
                if (attachment.Id != 0)
                    row = userDbDataSet.Attachments.FindById(attachment.Id);

                if (row == null)
                {
                    row = userDbDataSet.Attachments.NewAttachmentsRow();
                    row.MessageId = message.Id;
                    userDbDataSet.Attachments.AddAttachmentsRow(row);
                }

                row.MessageId = message.Id;
                row.Filename = attachment.Filename;
                row.Size = attachment.FileSize;
                row.Description = attachment.Description;
                row.Type = attachment.FileType;
                row.Uri = attachment.FileUri;
                row.LocalPath = attachment.LocalPath;
                row.AcceptChanges();
            }
            catch
            {
                OnErrorOccured("Failed to operate database.", true);
                userDbDataSet.Attachments.RejectChanges();
                return false;
            }
            return true;
        }

        private IViewer defaultViewer = new Javavaj.iHunter.Viewers.DefaultViewer();
        public IViewer GetViewer(string documentType)
        {
            return pluginManager.GetViewer(documentType);

        }

        /// <summary>
        /// 开始回复消息
        /// </summary>
        /// <remarks>
        /// 调用该方法后，ClientCore会通知插件准备回复消息，插件可能会引发RequestEdit事件
        /// </remarks>
        public void BeginReply(IMessage message)
        {
            IChannel channel = channels[message.ChannelHash];
            channel.NotifyReply(message);
            return;
        }

        ///<summary>
        ///GUI得到用户的回复输入后，将结果返回给ClientCore，接着ClientCore应该调用IChannel的Reply方法
        ///</summary>      
        public void ReplyDone(IChannel channel, IMessage source, IDictionary<string, object> replyinput,string tag)
        {
            bool result = channel.Reply(source, replyinput, tag);
            channel.Close();
            if (!result)
                OnErrorOccured("Reply failed.", true);

            return;

        }
        public DateTime GetChannelLastUpdateTime(IChannel channel)
        {
            try
            {
                return configManager.ChannelSettings[channel.ComputeHash()].LastUpdateTime;
            }
            catch
            {
                return DateTime.MinValue;
            }
        }
        public void SetChannelLastUpdateTime(IChannel channel, DateTime time)
        {
            DateTime oldTime = GetChannelLastUpdateTime(channel);
            configManager.ChannelSettings[channel.ComputeHash()] = new ChannelSettingItem()
            {
                LastUpdateTime = time
            };


        }
        /// <summary>
        /// 刷新频道的指定类别
        /// </summary>
        /// <param name="Channel">刷新的频道</param>
        /// <param name="category">刷新的类别</param>
        public void RefreshChannel(IChannel channel, DateTime startTime, DateTime endTime, string category)
        {
            //Step 1. Refresh all existing messages
            var existingHeaders = GetMessageHeaders(channel,category);
            foreach (IMessage header in existingHeaders)
            {
                IMessage message = GetMessage(header);
                if (message == null)
                    continue;
                RefreshMessage(message);


                if (!message.Read)
                    ApplyFilter(message);

                StoreMessage(channel, message);
            }

            //Step 2. Get new messages from 'startTime' to 'endTime'
            var messages = channel.GetMessages(startTime, endTime, null);

            foreach (var msg in messages)
            {
                if (!msg.Read)
                    ApplyFilter(msg);

                StoreMessage(channel, msg);
            }

        
        }

        public void TrainFilter(IMessage message)
        {
            foreach (IFilter filter in pluginManager.ListPlugins(PluginType.FilterPlugin))
            {
                filter.Train(message, !message.Spam);
            }

        }
        public void Filter(IMessage header)
        {
            IMessage messgage = GetMessage(header);
            ApplyFilter(messgage);
            UpdateMessage(messgage,false);
            header.Spam = messgage.Spam;
        }
        private void ApplyFilter(IMessage message)
        {
            message.Spam = false;
            foreach (IFilter filter in pluginManager.ListPlugins(PluginType.FilterPlugin))
            {
                int rank = configManager.GlobalSettings.Rank;
                if (filter.Rank(message) < rank)
                {
                    message.Spam = true;
                    break;
                }
            }
        }

        private void OnMessageChanged(IMessage header)
        {
            if (MessageChanged != null)
                MessageChanged.Invoke(this, new MessageChangedEventArgs(header));
        }

        private void CleanDeletedMessages()
        {
            var result = (from row in userDbDataSet.Messages
                          where (row.Status & 1) != 0 && (DateTime.Now - row.LastBuildTime).Hours > 48
                          select row).ToArray();
            foreach (var msg in result)
            {
                userDbDataSet.Messages.DeleteMessage(msg.Id);
            }

        }
        private void StoreMessage(IChannel channel, IMessage message)
        {
            try
            {
                //判断消息是新消息还是已有消息的更新
                int id = userDbDataSet.Messages.FindByUid(channel.ComputeHash(), message.Uid);
                IMessage msgIdHeader = null;
                if (id == 0)
                {
                    //新消息

                    msgIdHeader = NewMessage(channel);
                    message.Read = false;
                }
                else
                {
                    IMessage existingMessage = userDbDataSet.Messages.FindById(id).CreateMessage();
                    if (message.LastBuildTime > existingMessage.LastBuildTime)
                    {

                        //更新消息
                        //NOTE: 消息更新后，所有的附件被标记为无效，需要重新下载
                        msgIdHeader = new MessageHeader()
                        {
                            Id = id
                        };
                        message.Read = false;
                    }
                    else
                    {
                        if (message.SameAs(existingMessage))
                        {
                            if (message.Deleted)
                                return;

                            //重复消息，且没有更新
                            //更新数据库中可能的附加字段及相关表(例如附件是否下载)
                            UpdateMessage(message,false);
                            return;
                        }
                        else
                        {
                            //更新消息
                            //NOTE: 消息更新后，所有的附件被标记为无效，需要重新下载
                            msgIdHeader = new MessageHeader()
                            {
                                Id = id
                            };
                            message.Read = false;
                            message.LastBuildTime = DateTime.Now;

                        }
                    }
                }

                IMessage newMessage = new Message(channel)
                {
                    Id = msgIdHeader.Id,
                    Attachments = message.Attachments,
                    Author = message.Author,
                    Category = message.Category,
                    ChannelHash = channel.ComputeHash(),
                    Content = message.Content,
                    ContentType = message.ContentType,
                    Description = message.Description,
                    DueTime = message.DueTime,
                    Importance = message.Importance,
                    LastBuildTime = DateTime.Now,
                    Link = message.Link,
                    PubTime = message.PubTime,
                    Deleted = message.Deleted,
                    Spam = message.Spam,
                    Read = message.Read,
                    Repliable = message.Repliable,
                    Title = message.Title,
                    Uid = message.Uid
                };


                UpdateMessage(newMessage,true);
                OnMessageChanged(newMessage);
                return;
            }
            catch
            {
                OnErrorOccured("Failed to operate database.", true);
            }
        }

        /// <summary>
        /// 刷新某条指定的消息
        /// </summary>
        /// <param name="message">刷新的消息</param>
        public void RefreshMessage(IMessage message)
        {
            //FIXME
            IChannel channel = null;
            try
            {
                channel = channels[message.ChannelHash];
            }
            catch
            {
                channel = null;
            }
            if (channel == null)
                return;

            bool updated = channel.RefreshMessage(message);
     
            if (updated)
                ApplyFilter(message);

            StoreMessage(channel, message);
            
            if (!message.Read)
                updated = true;
            if (updated)
                OnMessageChanged(message);
            return;
        }

        /// <summary>
        /// 当用户要检索时，GUI调用此方法，ClientCore获取用户的输入，构造相应的ISearcher,对数据库进行检索
        /// </summary>
        /// <param name="keyword">关键字</param>
        /// <param name="from">开始日期</param>
        /// <param name="to">结束日期</param>
        public IMessage[] Search(string keyword, DateTime? from, DateTime? to)
        {
            List<ISearcher> searchers = new List<ISearcher>();
            if (keyword != null && keyword.Length != 0)
                searchers.Add(new KeywordSearcher(keyword));
            if (from.HasValue)
                searchers.Add(new StartTimeSearcher(from.Value));
            if (to.HasValue)
                searchers.Add(new EndTimeSearcher(to.Value));

            var result = from row in userDbDataSet.Messages
                         where Search(searchers, row)
                         select row.CreateMessageHeader();
            return result.ToArray();

        }

        private bool Search(IEnumerable<ISearcher> searchers, UserDbDataSet.MessagesRow row)
        {
            foreach (ISearcher searcher in searchers)
                if (!searcher.Match(row))
                    return false;
            return true;
        }
        /// <summary>
        /// 下载附件
        /// </summary>
        /// <param name="message">附件所在的消息对象</param>
        /// <param name="attach">附件对象</param>
        /// <param name="targetpath">保存位置</param>
        public void DownloadAttachment(IMessage message, IFileObject attach)
        {

            try
            {
                string path =
                 Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar +
                 "iHunter" + Path.DirectorySeparatorChar +
                 "Attachments";
                Directory.CreateDirectory(path);
                if (!channels[message.ChannelHash].Open())
                {
                    userDbDataSet.Attachments.RejectChanges();
                    return;
                }
                System.IO.Stream istream = channels[message.ChannelHash].DownloadFile(attach);
                if (istream == null)
                    return;

                string localPath = Path.GetFileName(Path.GetRandomFileName()) + "." + Path.GetExtension(attach.Filename);
                System.IO.Stream ostream = File.Open(Path.Combine(path, localPath), FileMode.Create);
                if (ostream == null)
                    return;

                byte[] buffer = new byte[1024];
                int nTotle = 0;
                while (true)
                {
                    int nRead = istream.Read(buffer, 0, 1024);
                    if (nRead == 0)
                        break;
                    nTotle += nRead;
                    ostream.Write(buffer, 0, nRead);
                }
                istream.Close();
                ostream.Close();

                attach.FileSize = nTotle;
                attach.LocalPath = Path.Combine(path, localPath);
                StoreAttachment(message, attach);
                userDbDataSet.Attachments.AcceptChanges();
            }
            catch
            {
                userDbDataSet.Attachments.RejectChanges();
            }
        }

        public Stream CreateAttachmentStream(IFileObject file)
        {
            string path =
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar +
                "iHunter" + Path.DirectorySeparatorChar +
                "Attachments";
            if (file.LocalPath.Length == 0)
                return null;

            try
            {
                string fullPath = Path.Combine(path, file.LocalPath);
                System.IO.Stream stream = File.Open(fullPath, FileMode.Open, FileAccess.Read);
                return stream;
            }
            catch
            {
                return null;
            }

        }

        public event MessageChangedEventHandler MessageChanged;
        public event EventHandler ChannelChanged;





        /// <summary>
        /// 保存数据库并关闭客户端
        /// </summary>
        /// <remarks>
        /// 可以再次调用Initialize方法来重新打开客户端
        /// </remarks>
        public void Close()
        {
            pluginManager.Cleanup();
            SaveDatabase();

        }

        private void pluginManager_PluginSettingChanged(object sender, PluginSettingChangedEventArgs e)
        {
            configManager.PluginSettings[e.Plugin.GetType().Assembly.FullName] = new PluginSettingItem()
            {
                AssemblyName = e.Plugin.GetType().Assembly.FullName,
                Enabled = true,
                Settings = e.Settings
            };
            userDbDataSet.PluginSettings.AcceptChanges();
            InitChannels();
        }


        public XmlDocument GetGlobalSettings()
        {

            XmlDocument settings = new XmlDocument();
            settings.AppendChild(settings.CreateElement("Settings"));
            settings.DocumentElement.AppendChild(settings.CreateElement("AutoUpdate"));
            settings.DocumentElement.AppendChild(settings.CreateElement("AutoUpdateInterval"));
            settings.DocumentElement.AppendChild(settings.CreateElement("AutoDownloadFile"));
            settings.DocumentElement.AppendChild(settings.CreateElement("AutoDownloadSizeLimit"));
            settings.DocumentElement.AppendChild(settings.CreateElement("Rank"));
            settings.DocumentElement.AppendChild(settings.CreateElement("Language"));

            settings.DocumentElement["AutoUpdate"].InnerText = configManager.GlobalSettings.AutoUpdate.ToString();
            settings.DocumentElement["AutoUpdateInterval"].InnerText = configManager.GlobalSettings.AutoUpdateInterval.ToString();
            settings.DocumentElement["AutoDownloadFile"].InnerText = configManager.GlobalSettings.AutoDownloadFile.ToString();
            settings.DocumentElement["AutoDownloadSizeLimit"].InnerText = configManager.GlobalSettings.AutoDownloadSizeLimit.ToString();
            settings.DocumentElement["Rank"].InnerText = configManager.GlobalSettings.Rank.ToString();
            settings.DocumentElement["Language"].InnerText = configManager.GlobalSettings.Language;
            return settings;

        }
        public void SetGlobalSettings(XmlDocument value)
        {
            configManager.GlobalSettings.AutoUpdate = bool.Parse(value.DocumentElement["AutoUpdate"].InnerText);
            configManager.GlobalSettings.AutoUpdateInterval = TimeSpan.Parse(value.DocumentElement["AutoUpdateInterval"].InnerText);
            configManager.GlobalSettings.AutoDownloadFile = bool.Parse(value.DocumentElement["AutoDownloadFile"].InnerText);
            configManager.GlobalSettings.AutoDownloadSizeLimit = long.Parse(value.DocumentElement["AutoDownloadSizeLimit"].InnerText);
            configManager.GlobalSettings.Rank = int.Parse(value.DocumentElement["Rank"].InnerText);
            configManager.GlobalSettings.Language = value.DocumentElement["Language"].InnerText;
        }

        private void OnErrorOccured(string message, bool critical)
        {
            if (ErrorOccured != null)
                ErrorOccured.Invoke(this, new ClientEventEventArgs(message, critical));
        }
        public event EditItemsEventHandler EditReply;
        public event ClientErrorEventHandler ErrorOccured;

        private void pluginManager_PluginError(object sender, PluginErrorEventArgs e)
        {
            PluginInformation info = e.Plugin;
            info.Enabled = false;
            pluginManager.SetPluginInfo(info);
            OnErrorOccured("Plugin error occured. The buggy plugin has been disabled.", true);
        }

        public void BeginPost(IChannel channel)
        {
            channel.NotifyReply(null);
        }

    }
}
